Skip to content

feat: Add text box editor for mokuro files - #146

Draft
Gnathonic wants to merge 13 commits into
developfrom
feature/text-box-editor
Draft

feat: Add text box editor for mokuro files#146
Gnathonic wants to merge 13 commits into
developfrom
feature/text-box-editor

Conversation

@Gnathonic

Copy link
Copy Markdown
Owner

Summary

Implements a comprehensive text box editing interface for mokuro files. Users can now visually edit text box positions, sizes, content, and font sizes with automatic optimization.

Features

Dedicated Edit Page

  • New route: /[manga]/[volume]/edit/[pageIndex]
  • Clean separation from reader - no hotkey conflicts or UI clutter
  • Single-page focus for precise editing

Visual Manipulation (5 Handles per Selected Box)

  • Move (top-left): Drag to reposition box
  • Delete (top-right, red trash icon): Remove box
  • Clone (bottom-left, green copy icon): Duplicate and drag to place
  • Resize (bottom-right, blue arrows): Adjust box dimensions
  • Auto-size (right side, amber text icon): Automatically optimize font size to fit

Non-Destructive Versioning

  • edited_pages field added to VolumeData type
  • Original mokuro data preserved in pages field
  • Reader automatically uses edited version when available
  • Save edits to IndexedDB
  • Export edited .mokuro JSON file

UI/UX Features

  • Zoom modes: Fit to Screen, Fit to Width, Original Size
  • Page navigation: Prev/Next with unsaved changes warning
  • Text editing: Click selected box to edit content inline
  • Real-time preview: See changes immediately

Testing

  • Text box selection and deselection
  • Move boxes with mouse drag
  • Resize boxes with resize handle
  • Delete boxes
  • Clone boxes with drag-to-place
  • Edit text content inline
  • Auto-size font optimization
  • Save to IndexedDB
  • Export .mokuro JSON
  • Page navigation with unsaved changes warning

🤖 Generated with Claude Code

Gnathonic and others added 13 commits November 9, 2025 12:41
Implements a dedicated editing interface for modifying text box positions,
sizes, text content, and font sizes with automatic optimization.

Core Features:
- Dedicated edit page route (/[manga]/[volume]/edit/[pageIndex])
- Visual manipulation with 5 handles per selected box:
  - Move handle (top-left): Drag to reposition
  - Delete handle (top-right): Remove box
  - Clone handle (bottom-left): Duplicate and place
  - Resize handle (bottom-right): Adjust dimensions
  - Auto-size handle (right side): Automatically optimize font size

Versioning System:
- Added edited_pages field to VolumeData for non-destructive editing
- Original mokuro data preserved in pages field
- Reader automatically uses edited version via getCurrentPages() utility
- Save edits to IndexedDB, export .mokuro JSON file

UI/UX:
- Zoom modes: Fit to Screen, Fit to Width, Original Size
- Page navigation with unsaved changes warning
- Real-time font size preview
- Auto-size algorithm: increases until overflow, then decreases to fit
- Text editing: Click selected box to edit content inline

Entry Point:
- Edit button added to QuickActions floating menu
- Page selector modal for dual-page view
- Seamless navigation between reader and editor

Closes #145

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…tate

Fixed DataCloneError that occurred when saving text box edits to IndexedDB. The issue was caused by attempting to store Svelte $state proxies and Dexie IndexedDB objects directly, which cannot be cloned by the structured clone algorithm.

## Changes
- Changed from `structuredClone()` to `JSON.parse(JSON.stringify())` for cloning pages
- Added serialization of `workingBlocks` before assignment to strip Svelte reactivity
- Updated comments to clarify the serialization is needed for both IndexedDB objects and Svelte proxies

## Technical Details
The error occurred in two places:
1. `currentPages` from Dexie had properties that couldn't be cloned
2. `workingBlocks` as a `$state` variable was wrapped in Svelte proxies

JSON serialization strips all non-serializable properties and proxies, leaving only plain data that IndexedDB can store.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Added visual indicators and the ability to revert edits to original mokuro data.

## Changes

**Visual Indicators:**
- Added yellow pencil badge to VolumeItem component (both list and grid views)
- Badge appears when a volume has edited pages
- Uses `hasEdits()` utility to check for `edited_pages` field

**Revert Functionality:**
- Added "Revert to Original" button in EditToolbar
- Button only appears when volume has edits
- Shows confirmation dialog before reverting
- Removes `edited_pages` field from database
- Reloads page data to show original content
- Shows success/error toasts

**Component Updates:**
- VolumeItem.svelte: Added `volumeHasEdits` state and pencil badge
- EditToolbar.svelte: Added `hasEdits` prop and revert button
- edit/+page.svelte: Added `volumeHasEdits` derived, `revertToOriginal()` function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Added a comparison modal that displays original and edited versions side-by-side.

## Changes

**Comparison Modal:**
- Added "Compare" button in EditToolbar (purple, appears when volume has edits)
- Modal shows original (left) and edited (right) versions side-by-side
- Color-coded borders: blue for original boxes, green for edited boxes
- Full-size view with scrollable containers
- Maximum width set to 90vw for better visibility

**Technical Details:**
- Added `originalPageData` derived value using `getOriginalPages()`
- Added `showCompareModal` state for modal visibility
- Modal renders both versions with identical styling to editor
- Shows text boxes with proper font sizes, writing modes, and line breaks

**Component Updates:**
- EditToolbar.svelte: Added Compare button and onCompare prop
- edit/+page.svelte: Added comparison modal with side-by-side layout

This helps users visualize their changes before saving or reverting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Changed from ArrowRotateBackwardSolid (doesn't exist) to UndoOutline.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Removed the comparison modal and added the ability to create new text boxes.

## Changes

**Add Textbox Button:**
- Added purple "Add Textbox" button in EditToolbar
- Creates new empty text box in center of page
- Default size: 200x100px, font size 20px
- Auto-selects new box for immediate editing
- Marks page as having unsaved changes

**Removed Features:**
- Removed comparison modal (original vs edited view)
- Removed onCompare callback and related code
- Removed unused imports (getOriginalPages, Modal)

**Component Updates:**
- EditToolbar.svelte: Replaced Compare button with Add Textbox
- edit/+page.svelte: Added addTextbox() function, removed compare modal

This makes it easier to add custom text annotations to manga pages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed two issues:
1. Changed PlusSolid to CirclePlusSolid (correct Flowbite icon name)
2. Added separate toast for revert operations to avoid confusion

## Changes
- EditToolbar.svelte: Use CirclePlusSolid instead of PlusSolid
- edit/+page.svelte: Added showRevertSuccess state and toast
- Revert now shows "Reverted to original" instead of "Edits saved successfully"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Implemented automatic font sizing during resize operations and removed the redundant manual auto-size button.

## Changes

**Auto-resize during drag:**
- Font size now automatically adjusts as you resize a text box
- Throttled to every 10th frame for smooth performance
- Final auto-size runs when resize completes for perfect fitting
- Uses fast overflow detection to increase/decrease font size

**Removed manual button:**
- Removed auto-size button (now redundant)
- Removed TextSizeOutline icon import
- Removed handle-font-auto CSS styles
- Updated resize handle tooltip to indicate auto-sizing

**Bug fixes:**
- Added data-block-index attribute for DOM queries
- Added text-container class for overflow detection
- Fixed page navigation not updating text boxes
- Added $effect to reload workingBlocks on page change
- Removed transition-all for instant position updates
- Fixed Modal import that was accidentally removed
- Fixed toast showing on page load with isMounted guard

**Technical improvements:**
- Used JSON serialization instead of structuredClone for Svelte state
- Throttled auto-size to prevent blocking resize operations
- requestAnimationFrame for non-blocking font updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Resolved merge conflicts:
- QuickActions.svelte: Migrated from SpeedDial to custom buttons + added edit feature
- Reader.svelte: Added editor props (currentPage, showSecondPage)
- VolumeItem.svelte: Combined edits badge with image-only badge

Updated editor components for Flowbite v1:
- EditToolbar.svelte: on:change → onchange for Select
- Edit page: on:click → onclick for Button, updated Toast API to use snippets and conditional rendering
@vercel

vercel Bot commented Jan 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
mokuro-reader Ready Ready Preview, Comment Jan 19, 2026 5:31pm

@Gnathonic
Gnathonic changed the base branch from main to develop January 23, 2026 13:51
vncthar pushed a commit to vncthar/mokuro-reader that referenced this pull request Mar 10, 2026
…sistency

fix: Implement consistent Japanese text rendering across all platforms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant